<?php
	function duplica(&$o)
	{
		return $o;
	}
	class xml
	{
		var $tag;
		var $att;
		var $chl;

		public function __construct($t)
		{
			$this->tag = $t;
			//$this->chl = array();
		}

		function __clone()
		{
			$this->chl = clone $this->chl;
		}
	}

	$x = new xml("aaa");
	$x->att = array("a", "b", "c");
	$x->chl = new xml("child");

	$x2 = clone $x;
	$x2->tag = "no";
	$x2->att[0] = "no";
	$x2->chl->tag = "nono";

	echo "<pre>";
	print_r($x);
	print_r($x2);
	echo "</pre>";



	return;


	class xml
	{
		var $tag;
		var $att;
		var $chl;

		public function __construct($t)
		{
			$this->tag = $t;
			$this->chl = array();
		}
	}
	$data = html_trim(file_get_contents("data.xml"));
echo '<pre>';

	// rimuove tutti gli spazi inutili tra i tag
	function html_trim($s){
		$ret = "";
		$l = strlen($s)-1;
		for($i=0;$i<$l; $i++)
		{
			if($s[$i]==">")
			{
				$j = $i+1;
				while($j<$l && ($s[$j]==" " || $s[$j]=="\r" ||
					$s[$j]=="\n" || $s[$j]=="\t"))
				{
					$j++;
				}
				if($s[$j]=="<")
				{
					$ret .= $s[$i];
					$i = $j;
				}
			}
			$ret .= $s[$i];
		}
		if($i==$l) $ret .= $s[$i];
		return $ret;
	}
//	echo htmlentities();
//	echo "<hr>";

//@<\*(.*)\*>(.*)</\*(.*)\*>@Usi
//<([^"]*"|'[^']*'|[^'">])*>
	//$pos = -1;
//	while(($pos = preg_match("/<module[^>]*\/>/", $data, $matches)))
	//preg_match_all("/(?P<name><module)(?P<attr>.*\)/>/", $data, $matches, PREG_OFFSET_CAPTURE);
	//preg_match_all("/<\/?(?P<name>group[^>]|module[^>])(?P<attr>[^>\/]*)\/*>/", $data, $matches, PREG_OFFSET_CAPTURE);
	class CLayoutGroup
	{
		var $tag;
		var $att;
		var $chl;

		public function __construct($t)
		{
			$this->tag = $t;
			$this->chl = array();
		}
	}
	class CModuleContainer
	{
		var $tag;
		var $att;
		var $chl;

		public function __construct($t)
		{
			$this->tag = $t;
			$this->chl = array();
		}

		public function display()
		{
			$ret = "";
			foreach($this->chl as $o)
			{
				if(is_subclass_of($o, "AModule"))
				{

				}
				$ret .= $o;
			}
		}
	}

	$root = new CLayoutGroup("root");
	$current = $root;
	$stack = array();
	// OK --> preg_match_all("/<\/?(?P<name>group *|module *)(?P<attr>[^>\/]*)\/*>/", $data, $matches);
	preg_match_all("/<(\/?group|module) *([^>\/]*)\/*>/", $data, $matches, PREG_OFFSET_CAPTURE);
	$lastpos = 0;
	foreach($matches[1] as $k => $m)
	{
		$tag = $m[0];
		$pos = $m[1];
		$atr = array();

		preg_match_all("/([^ ]*)=\"([^ ]*)\" */", $matches[2][$k][0], $attrs);
		foreach($attrs[1] as $atrk => $atr_name)
		{
			$atr[$atr_name] = $attrs[2][$atrk];
		}
		if($tag=="group")
		{
			array_push($current->chl, substr($data, $lastpos, $pos-$lastpos-1));
			array_push($stack, $current);
			$grp = new CLayoutGroup($tag);
			$grp->att = $atr;
			array_push($current->chl, $grp);
			$current = $grp;
		}
		elseif($tag=="/group")
		{
			array_push($current->chl, substr($data, $lastpos, $pos-$lastpos-1));
			$current = array_pop($stack);
		}
		elseif($tag=="module")
		{
			array_push($current->chl, substr($data, $lastpos, $pos-$lastpos-1));
			array_push($current->chl, "$tag ".$matches[2][$k][0]);
		}
		else continue;
		$lastpos = $matches[0][$k][1] + strlen($matches[0][$k][0]);
	}
	array_push($current->chl, substr($data, $lastpos, strlen($data)-$lastpos));

	//preg_match_all("/<\/(?P<name>group[^>]*|module[^>]*)>/", $data, $matches, PREG_OFFSET_CAPTURE);
	//preg_match_all("/<\/(?P<name>group[^>]*|module[^>]*)>/", $data, $matches, PREG_OFFSET_CAPTURE);
$attr=" name=\"title\" titti=\"asd\"";
//preg_match_all("/((?P<attr>[^ ]*)=\"(?P<val>[^ ]*))\" */", $attr, $matches);

	//echo htmlentities($data);
	echo htmlentities(print_r($current, true));
	//echo htmlentities(print_r($matches, true));
echo '</pre>';
	return;


    $parser = xml_parser_create('UTF-8');
    xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
    xml_set_element_handler($parser, 'tag_open', 'tag_close');
    xml_set_character_data_handler($parser, 'cdata');

    $root = new xml("root");
    $stack = array($root);

    xml_parse($parser, $data);

    print_r($root);

    function tag_open($parser, $tag, $attribs)
    {
    	global $stack;
    	global $root;
        print_r($root);
    	//if(!isset($actual->chl)) $actual->chl = array();
    	$tmp = new xml($tag);
    	$tmp->att = $attribs;
    	array_push($root->chl, $tmp);
    	array_push($stack, $tmp);
    	$root = $tmp;
    	$next = $tmp;
        echo "\napertura $tag <br>\n";
    }

    function cdata($parser, $cdata)
    {
    	global $root;
    	//$actual->cdata = $cdata;
		//echo "\"$cdata \"<br>\n";
    }

    function tag_close($parser, $tag)
    {
    	global $stack;
    	global $root;
		$root = array_pop($stack);
		echo "chiusura $tag <br>\n";
    }
    function printxml(xml &$tag)
	{
    	echo $tag->tag;
    }
?>